package com.inifitness.common.tools;

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Optional;
import java.util.Set;

import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;

import com.inifitness.common.annotations.Dict;
import com.inifitness.common.basic.BaseEnum;
import com.inifitness.common.constants.RedisKey;
import com.inifitness.common.constants.RedisKey.Prefix;

import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.core.type.filter.AssignableTypeFilter;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

/**
 * 枚举<=>数据字典缓存工具
 *
 * @author sunjinfeng
 * @version 1.0.0
 * @since 2024/04/18 11:00:00
 */
@Log4j2
@Component
public class EnumToDictCacheTools {

  @Resource
  private RedisTemplate<String, Map<String, String>> redisTemplate;

  private static EnumToDictCacheTools enumToDictCacheTools;

  @PostConstruct
  public synchronized void init() {
    if (enumToDictCacheTools == null) {
      enumToDictCacheTools = this;
    }
  }

  /**
   * 将BaseEnum下的枚举转换为数据字典以加载到Redis缓存中
   *
   * @author sunjinfeng
   * @since 2024/04/18 11:00:00
   **/
  public static void loadEnumToDictCache() {
    log.info(">>>>开始进行枚举信息转数据字典");
    ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(
        false);
    provider.addIncludeFilter(new AssignableTypeFilter(BaseEnum.class));
    provider.addIncludeFilter(new AnnotationTypeFilter(Dict.class));
    Set<BeanDefinition> components = provider.findCandidateComponents("com.inifitness");

    for (BeanDefinition component : components) {
      Class<?> clazz = null;
      try {
        clazz = Class.forName(component.getBeanClassName());
      } catch (ClassNotFoundException e) {
        log.warn("Bean对象不存在", e);
        continue;
      }

      if (clazz.isEnum()) {
        BaseEnum<?>[] items = (BaseEnum<?>[]) clazz.getEnumConstants();

        Map<String, String> result = new LinkedHashMap<>();
        for (BaseEnum<?> item : items) {
          result.put(item.getValue().toString(), item.getLabel());
        }

        Dict dict = clazz.getAnnotation(Dict.class);
        String key = Optional.ofNullable(dict).map(Dict::code).orElse(clazz.getSimpleName());

        enumToDictCacheTools.redisTemplate.opsForHash()
            .putAll(RedisKey.getKey(Prefix.DICT_PREFIX, key), result);
      }
    }
  }
}
